package com.maning.mndialoglibrary.view;


import ohos.agp.animation.Animator.CurveType;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * Created by Mikhael LOPEZ on 16/10/2015.
 * 引用：https://github.com/lopspower/CircularProgressBar
 */
public class MNHudCircularProgressBar extends Component implements Component.DrawTask,
        Component.EstimateSizeListener{

    // Properties
    private float progress = 0;
    private float lastProgress = 0;
    private float strokeWidth = 10;
    private float backgroundStrokeWidth = 10;
    private Color color =Color.BLACK;
    private Color backgroundColor = Color.GRAY;
    //动画时长
    private long mDuration = 300;

    // Object used to draw
    private int startAngle = -90;
    private RectFloat rectF;
    private Paint backgroundPaint;
    private Paint foregroundPaint;

    //region Constructor & Init Method
    public MNHudCircularProgressBar(Context context, AttrSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttrSet attrs) {
        rectF = new RectFloat();


        // Init Background
        backgroundPaint = new Paint();
        backgroundPaint.setColor(backgroundColor);
        backgroundPaint.setStyle(Paint.Style.STROKE_STYLE);
        backgroundPaint.setStrokeWidth(backgroundStrokeWidth);

        // Init Foreground
        foregroundPaint = new Paint();
        foregroundPaint.setColor(color);
        foregroundPaint.setStyle(Paint.Style.STROKE_STYLE);
        foregroundPaint.setStrokeWidth(strokeWidth);
        // 获取屏幕的宽高度、中心点坐标，调用onEstimateSize方法
        setEstimateSizeListener(this);
        // 添加绘制任务，调用onDraw方法
        addDrawTask(this);
    }
    //endregion

    //region Draw Method
    @Override
    public void onDraw(Component component, Canvas canvas) {
        canvas.drawOval(rectF, backgroundPaint);
        float angle = 360 * progress / 100;
        canvas.drawArc(rectF, new Arc(startAngle,angle,false), foregroundPaint);
    }
    //endregion

    //region Mesure Method
    @Override
    public boolean onEstimateSize(int i, int i1) {
        int height = EstimateSpec.getSize(i);
        int width = EstimateSpec.getSize(i1);
        final int min = Math.min(width, height);
        setEstimatedSize(
                EstimateSpec.getChildSizeWithMode(width, height, EstimateSpec.PRECISE),
                EstimateSpec.getChildSizeWithMode(width, height, EstimateSpec.PRECISE)
        );
        float highStroke = (strokeWidth > backgroundStrokeWidth) ? strokeWidth : backgroundStrokeWidth;
        rectF.modify(0 + highStroke / 2, 0 + highStroke / 2, min - highStroke / 2, min - highStroke / 2);
        return true;
    }
    //endregion

    //region Method Get/Set
    public float getProgress() {
        return progress;
    }

    public void setProgress(float progress) {
        setProgress(progress, true);
    }

    public void setProgress(float progress, boolean animal) {
        this.progress = (progress <= 100) ? progress : 100;
        if (animal) {
            //开启动画
            startAnim();
            this.lastProgress = progress;
        } else {
            invalidate();
        }

    }

    //动画
    public void startAnim() {
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setCurveType(CurveType.ACCELERATE_DECELERATE);
        animatorValue.setDuration(mDuration);
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                progress = v;
                invalidate();
            }
        });
        animatorValue.start();
    }

    public float getProgressBarWidth() {
        return strokeWidth;
    }

    public void setProgressBarWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
        foregroundPaint.setStrokeWidth(strokeWidth);
        postLayout();//Because it should recalculate its bounds
        invalidate();
    }

    public float getBackgroundProgressBarWidth() {
        return backgroundStrokeWidth;
    }

    public void setBackgroundProgressBarWidth(float backgroundStrokeWidth) {
        this.backgroundStrokeWidth = backgroundStrokeWidth;
        backgroundPaint.setStrokeWidth(backgroundStrokeWidth);
        postLayout();//Because it should recalculate its bounds
        invalidate();
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
        foregroundPaint.setColor(color);
        invalidate();
        postLayout();
    }

    public Color getBackgroundColor() {
        return backgroundColor;
    }

    public void setBackgroundColor(Color backgroundColor) {
        this.backgroundColor = backgroundColor;
        backgroundPaint.setColor(backgroundColor);
        invalidate();
        postLayout();
    }
    //endregion

    //region Other Method

    /**
     * Set the progress with an animation.
     *
     * @param progress The progress it should animate to it.
     */
    public void setProgressWithAnimation(float progress) {
        setProgressWithAnimation(progress, 1500);
    }

    /**
     * Set the progress with an animation.
     *
     * @param progress The progress it should animate to it.
     * @param duration The length of the animation, in milliseconds.
     */
    public void setProgressWithAnimation(float progress, int duration) {
        AnimatorValue objectAnimator = new AnimatorValue();
        objectAnimator.setDuration(duration);
        objectAnimator.setCurveType(CurveType.DECELERATE);
        objectAnimator.start();
    }
    //endregion
}
